<?php

/**
 * The Util class has methods for different utilities.
 * 
 * @author Cesar Augustus Silva <cesaraugustussilva@linuxmail.org>
 * @copyright Copyright (c) 2013, Cesar Augustus Silva
 * @license http://www.gnu.org/licenses/gpl.html GNU GPL v3.0
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <­http://www.gnu.org/licenses/>.
 */
class Util {

    /**
     * Checks if the cpf/cnpj already exists in the registry
     * 
     * @param int $cpfcnpj The cpf/cnpj to check
     * @return boolean <b>TRUE</b> if cpf exists or <b>FALSE</b> if not exists
     */
    public static function cpfcnpj_exists($cpfcnpj) {
        if (strlen($cpfcnpj) == 11) {
            if (DbGet::customer(null, $cpfcnpj))
                return true;
        }
        else
            if (DbGet::enterprise(null, $cpfcnpj))
                return true;
        return false;
    }
    
    /**
     * Checks if the email already exists in the account
     * 
     * @param string $email The email address
     * @return boolean <b>TRUE</b> if email exists or <b>FALSE</b> if not exists
     */
    public static function email_exists($email) {
        if (DbGet::account($email, '%'))
            return true;
        else
            return false;
    }
    
    /**
     * Formats a number with the formation of cep
     * 
     * @param float $number The floating point number
     * @return string The string with format cep
     */
    public static function format_cep($number) {
        if (preg_match('/^(\d{2})(\d{3})(\d{3})$/', $number, $matches))
            return $matches[1].'.'.$matches[2].'-'.$matches[2];
        else
            return $number;
    }
    
    /**
     * Formats a number with the formation of money
     * 
     * @param float $number The floating point number
     * @param int [optional]<br>The number of decimal places
     * @return string The string with format money
     */
    public static function format_money($number, $decimal = 2) {
        return number_format($number, $decimal, ',', '.');
    }
    
    /**
     * Formats a number with the formation of phone
     * 
     * @param float $number The floating point number
     * @return string The string with format phone
     */
    public static function format_phone($number) {
        if (preg_match('/^(\d{4})(\d{4})$/', $number, $matches))
            return $matches[1].'-'.$matches[2];
        elseif (preg_match('/^(\d{5})(\d{4})$/', $number, $matches))
            return $matches[1].'-'.$matches[2];
        elseif (preg_match('/^(\d{2})(\d{4})(\d{4})$/', $number, $matches))
            return '('.$matches[1].') '.$matches[2].'-'.$matches[3];
        elseif (preg_match('/^(\d{2})(\d{5})(\d{4})$/', $number, $matches))
            return '('.$matches[1].') '.$matches[2].'-'.$matches[3];
        else
            return $number;
    }
    
    /**
     * Cut the string by the length specified without cuts in the middle of a word
     * 
     * @param string $string The input string
     * @param int $length [optional]<br>The character length
     * @return string Returns the extracted part of string
     */
    public static function glance($string, $length = 0) {
        $string = strip_tags($string);
        $string = preg_replace('/&#?[a-z0-9]+;/si', '', $string);
        $string = preg_replace('/[\t\n\s]+/si', ' ', $string);
        if ($length) {
            while ($string[$length-1] != ' ' && $length > 0)
                $length--;
            $string = trim(substr($string, 0, $length-1)).'...';
        }
        else
            $string = trim($string);
        return $string;
    }
    
    /**
     * Checks if the number is a valid CPF/CNPJ
     * 
     * @param string $number The input number
     * @return boolean <b>TRUE</b> if valid or <b>FALSE</b> if not valid
     */
    public static function is_cpfcnpj($number) {
        $number_verifier = str_split($number);
        if (count($number_verifier) == 11)
            $cpfcnpj = array_splice ($number_verifier, 0, 9);
        elseif (count($number_verifier) == 14)
            $cpfcnpj = array_splice($number_verifier, 0, 12);
        else {
            echo 'Esse CPF/CNPJ é inválido.';
            return false;
        }
        
        $verifier = array();
        for ($n = 0; $n < 2; $n++) {
            $sum = 0;
            $default = array();
            if (count($cpfcnpj) < 11) {
                for ($i = 10+$n; $i > 1; $i--)
                    $default[] = $i;
            }
            else {
                for ($i = 5+$n; $i > 1; $i--)
                    $default[] = $i;
                for ($i = 9; $i > 1; $i--)
                    $default[] = $i;
            }
            for ($i = 0; $i < count($cpfcnpj)+$n; $i++)
                $sum += $cpfcnpj[$i] * $default[$i];
            $result = $sum % 11;
            $verifier[$n] = ($result < 2) ? 0 : 11 - $result;
            if ($n == 0)
                $cpfcnpj[count($cpfcnpj)] = $verifier[$n];
        }
        unset($cpfcnpj[count($cpfcnpj)-1]);
        $rtn = false;
        if ($number_verifier == $verifier)
            $rtn = true;
        $cpfcnpjver = array_merge($cpfcnpj, $number_verifier);
        if (count(array_unique($cpfcnpjver)) == 1
                || $cpfcnpjver == array(0,1,2,3,4,5,6,7,8,9,0)
                || $cpfcnpjver == array(0,1,2,3,4,5,6,7,8,9,0,1,2,3))
            $rtn = false;
        if (!$rtn) {
            if (count($cpfcnpjver) == 11)
                echo 'Esse CPF é inválido.';
            else
                echo 'Esse CNPJ é inválido.';
        }
        return $rtn;
    }
    
    /**
     * Checks if the string is a valid email and if exists
     * 
     * @param string $string The input string
     * @return boolean <b>TRUE</b> if valid email or <b>FALSE</b> if not valid email
     */
    public static function is_email($string){
        if (preg_match('/^([a-z0-9])+([a-z0-9\._-])*@([a-z0-9_-])+([a-z0-9\._-]+)+$/i', $string)) {
            list($username, $domain) = explode('@', $string);
            if (!checkdnsrr($domain, 'MX')) {
                echo 'Esse endereço de e-mail não existe.';
                return false;
            }
        }
        else {
            echo 'Informe um endereço de e-mail válido.';
            return false;
        }
        return true;
    }
    
    /**
     * Checks if the account is already logged
     * 
     * @return boolean <b>TRUE</b> if logged or <b>FALSE</b> if not logged
     */
    public static function is_logged() {
        $session = new Session('account');
        if (isset($session->email) && isset($session->password)) {
            if (DbGet::account($session->email, $session->password))
                return true;
        }
        return false;
    }
    
    /**
     * Checks if the string is a md5 hash
     * 
     * @param string $md5 The input string
     * @return boolean <b>TRUE</b> if md5 hash or <b>FALSE</b> if not hash md5
     */
    public static function is_md5($string) {
        if (!empty($string) && preg_match('/^[a-f0-9]{32}$/', $string) == 1)
            return true;
        else
            return false;
    }
    
    /**
     * Opens a session of the account
     * 
     * @param string $email The email address to login
     * @param string $password The password to login
     * @param int $persistent [optional]<br>A alias to define if session will persistent
     * @return int <b>1</b> on success, <b>0</b> on invalid or<b>-1</b> on inactive
     */
    public static function login_account($email, $password, $persistent = 0) {
        if ($account = DbGet::account($email, $password)) {
            if ($account->active) {
                $data = array(
                    'id_account' => $account->id,
                    'type_account' => $account->type
                );
                DbSet::accesslogs($data);
                $session = new Session('account', $persistent);
                $session->id = $account->id;
                $session->type = $account->type;
                $session->email = $account->email;
                $session->password = $account->password;
                return 1;
            }
            else
                return -1;
        }
        else
            return 0;
    }
    
    /**
     * Closes the open session
     * 
     * @return void No value is returned
     */
    public static function logout_account() {
        $session = new Session('account');
        $session->destroy();
    }
    
    /**
     * Get the latest news by rss
     * 
     * @param int $total [optional]<br>The total news to be obtained
     * @return array|boolean Returns news obtained or <b>FALSE</b> on failure
     */
    public static function news_rss($total = 0) {
        $url = 'http://g1.globo.com/dynamo/carros/rss2.xml';
        $file = file_get_contents($url);
        if ($file == false)
            return false;
        $xml = simplexml_load_string($file);
        $n = 0;
        $data = array();
        foreach ($xml->channel->item as $item) {
            $data[$n] = new stdClass;
            $data[$n]->title = $item->title;
            $data[$n]->link = $item->link;
            $data[$n]->description = self::glance($item->description);
            preg_match_all('|<img .*src=["\'](.*)["\'].*/>|U',$item->description,$out);
            $data[$n]->image = $out[1][0];
            if (++$n == $total)
                break;
        }
        return $data;
    }
    /**
     * Creates the menu pagination
     * 
     * @param int $pg The page number
     * @param int $npp The number of contents per page
     * @param int $num_rows The total number of rows
     * @param string $url [optional]<br>The url menus pagination
     * @return stdClass The menu creation in html and its properties
     */
    public static function pagination($pg, $npp, $num_rows, $url = '') {
        if ($num_rows) {
            $num_pg = $num_rows/$npp;
            if ($num_pg - (integer) $num_pg > 0)
                $num_pg = (integer) ($num_pg + 1);
            if (!(is_numeric($pg)) || ($pg < 1))
                $pg = 1;
            elseif ($pg > $num_pg)
                $pg = $num_pg;
            else
                $pg = (int) $pg;
            $pagination->num_rows = $num_rows;
            $pagination->num_pg = $num_pg;
            $pagination->pg = $pg;
            $pagination->html = '<ul>';
            //if ($num_pg > 5 && $pg > 3)
            //    $pagination->html .= '<li class="first"><a href="'.__BASE_URI__.$url.'pagina.1">Início</a></li>';
            if ($pg > 1)
                $pagination->html .= '<li class="previous"><a href="'.__BASE_URI__.$url.'pagina.'.($pg - 1).'">Anterior</a></li>';
            if ($num_pg > 4 && $pg == $num_pg)
                $pagination->html .= '<li><a href="'.__BASE_URI__.$url.'pagina.'.($pg - 4).'">'.($pg - 4).'</a></li>';
            if ($num_pg > 3 && $pg - 2 > 1 && $pg >= $num_pg - 1)
                $pagination->html .= '<li><a href="'.__BASE_URI__.$url.'pagina.'.($pg - 3).'">'.($pg - 3).'</a></li>';
            if ($pg >= 3)
                $pagination->html .= '<li><a href="'.__BASE_URI__.$url.'pagina.'.($pg - 2).'">'.($pg - 2).'</a></li>';
            if ($pg >= 2)
                $pagination->html .= '<li><a href="'.__BASE_URI__.$url.'pagina.'.($pg - 1).'">'.($pg - 1).'</a></li>';
            $pagination->html .= '<li class="active"><a href="'.__BASE_URI__.$url.'pagina.'.$pg.'">'.$pg.'</a></li>';
            if ($pg <= $num_pg - 1)
                $pagination->html .= '<li><a href="'.__BASE_URI__.$url.'pagina.'.($pg + 1).'">'.($pg + 1).'</a></li>';
            if ($pg <= $num_pg - 2)
                $pagination->html .= '<li><a href="'.__BASE_URI__.$url.'pagina.'.($pg + 2).'">'.($pg + 2).'</a></li>';
            if ($num_pg > 3 &&  $pg + 2 < $num_pg && $pg <= 2)
                $pagination->html .= '<li><a href="'.__BASE_URI__.$url.'pagina.'.($pg + 3).'">'.($pg + 3).'</a></li>';
            if ($num_pg > 4 && $pg == 1)
                $pagination->html .= '<li><a href="'.__BASE_URI__.$url.'pagina.'.($pg + 4).'">'.($pg + 4).'</a></li>';
            if ($pg < $num_pg)
                $pagination->html .= '<li class="next"><a href="'.__BASE_URI__.$url.'pagina.'.($pg + 1).'">Próximo</a></li>';
            //if ($num_pg > 5 && $pg < $num_pg - 2)
            //    $pagination->html .= '<li class="last"><a href="'.__BASE_URI__.$url.'pagina.'.$num_pg.'">Último</a></li>';
            $pagination->html .= '</ul>'."\n";
            return $pagination;
        }
        else
            return false;
    }
    
    /**
     * Parses a string with format money and returns a floating point number
     * 
     * @param string $money The string with format money
     * @return float The floating point number
     */
    public static function parse_float($money) {
        return floatval(str_replace(',', '.', preg_replace('/[^\d,]/', '', $money)));
    }

    /**
     * Checks if the renavam already exists in the registers of the account
     * 
     * @param int $id The identity of the account
     * @param string $renavam The renavam to check
     * @return int|boolean The id of the vehicle ad or <b>FALSE</b> if not exists
     */
    public static function renavam_exists($id, $renavam) {
        if ($customer_vehicles = DbGet::customer_vehicles($id)) {
            foreach ($customer_vehicles as $customer_vehicle)
                if ($customer_vehicle->v_renavam == $renavam)
                    return $customer_vehicle->c_id;
        }
        if ($enterprise_vehicles = DbGet::enterprise_vehicles($id)) {
            foreach ($enterprise_vehicles as $enterprise_vehicle)
                if ($enterprise_vehicle->v_renavam == $renavam)
                    return $enterprise_vehicle->e_id;
        }
        return false;
    }
    
    /**
     * View the banners according the type defined
     * 
     * @param int|string $type The type of banner.<br>If string types are:
     *                  <b>top</b>, <b>tv</b>, <b>middle</b>,
     *                  <b>lateral</b>, <b>search</b> and <b>lateral2</b>.
     * @param int $quantity [optional]<br>The quantity of banners
     * @return array The data of the banners
     */
    public static function view_banners($type, $quantity = null) {
        if (!is_numeric($type)) {
            $type = strtolower($type);
            switch ($type) {
                case 'top':
                    $type = 1;
                    $quantity = ($quantity == null) ? 1 : $quantity;
                    break;
                case 'tv':
                    $type = 2;
                    $quantity = ($quantity == null) ? 1 : $quantity;
                    break;
                case 'middle':
                    $type = 3;
                    $quantity = ($quantity == null) ? 3 : $quantity;
                    break;
                case 'lateral':
                    $type = 4;
                    $quantity = ($quantity == null) ? 9 : $quantity;
                    break;
                case 'search':
                    $type = 5;
                    $quantity = ($quantity == null) ? 1 : $quantity;
                    break;
                case 'lateral2':
                    $type = 6;
                    $quantity = ($quantity == null) ? 16 : $quantity;
                    break;
                case 'lateral3':
                    $type = 7;
                    $quantity = ($quantity == null) ? 2 : $quantity;
                    break;
                default:
                    die('This type of banner is not in the list.');
                    break;
            }
        }
        $banners = DbGet::banners($type, $quantity);
        if ($banners) {
            if (count($banners) != $quantity) {
                DbSet::banners(array('viewed' => null), $type);
                $id_viewed = array();
                foreach ($banners as $banner)
                    $id_viewed[] = $banner->id;
                DbSet::banners(array('viewed' => 'X'), $type, $id_viewed);
                $wantage = $quantity - count($banners);
                $banners2 = self::view_banners($type, $wantage);
                if (is_array($banners2)) {
                    foreach ($banners2 as $banner) {
                        $exists = false;
                        foreach ($banners as $obj)
                            if ($banner->filepicture == $obj->filepicture)
                                $exists = true;
                        if ($exists)
                            $banners[] = array();
                        else
                            $banners = array_merge($banners, array($banner));
                    }
                }
                else {
                    $exists = false;
                    foreach ($banners as $obj)
                        if ($banners2->filepicture == $obj->filepicture)
                            $exists = true;
                    if ($exists)
                        $banners[] = array();
                    else
                        $banners = array_merge($banners, array($banners2));
                }
            }
            else {
                $id_viewed = array();
                foreach ($banners as $banner)
                    $id_viewed[] = $banner->id;
                DbSet::banners(array('viewed' => 'X'), $type, $id_viewed);
            }
        }
        else {
            if (DbGet::banners($type, $quantity, true)) {
                DbSet::banners(array('viewed' => null), $type);
                $banners = self::view_banners($type, $quantity);
            }
            else {
                $banners = array();
                for ($x = 0; $x < $quantity; $x++)
                    $banners[] = array();
            }
                
        }
        if (is_array($banners) && count($banners) == 1)
            $banners = $banners[0];
        return $banners;
    }

}